import datetime
import json
import os
import re
import time

import pymysql
import requests
import xlwt

from commons import request_data
from commons.request_data import COMMAND_DICT_LIST, STORAGE_STATUS
from utils.yaml_utils import write_yaml, clean_yaml, write_excel, write_json
from utils.func_utils import DBUtils, RequestUtils


class UsefulTools:
    def __init__(self, env="test"):
        self.env = env
        self.headers = {
            "X-AUTH-SOURCE": "SSO",
            "Cookie": DBUtils().get_token(self.env),
            "Content-Type": "application/json; charset=UTF-8",
            "x-sys-key": "iov",
            'Connection': 'close'
        }

    def checkout_env(self, now_env, tar_env, ecu):
        """
        功能：切换ECU所在环境
        :return: -
        """
        if now_env == "test":
            command_url = "http://test-os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/send"
            confirm_url = "http://test-os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/result"
        elif now_env == "online":
            command_url = "http://os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/send"
            confirm_url = "http://os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/result"

        if tar_env == "test":
            tar_url = "DOMAIN=TEST-RADAR.SONGGUO7.COM:1024"
        elif tar_env == "online":
            tar_url = "DOMAIN=RADAR.SONGGUO7.COM:1024"

        params = {
            "params": {
                "steStr": ecu,
                "channel_type": "NET",
                "command_type": "331",
                "need_ack": False,
                "ste_sns": [
                    ecu
                ],
                "tenant_code": "1",
                "param": tar_url
            }
        }

        res = requests.post(command_url, json=params, headers=DBUtils().get_headers)
        confirm_params = {
            "params": {
                "command_nos": [res.json()["data"]["send_success_commands"][0]["command_no"]]
            }
        }
        res = requests.post(self.confirm_url, json=confirm_params, headers=self.headers)
        return res.json()["data"][0]["command_result"]

    def bind_bike(self, ecu_sn, bike_sn):
        """
        功能：测试环境绑定车辆到ecu
        :param ecu_sn: ecu_sn
        :param bike_sn: 车辆编号
        :return: -
        """
        if self.env == "test":
            url = "http://test-inside-ebike-info-api.songguo7.com/ebike/ebike/bind"
        elif self.env == "online":
            print("online环境不支持绑定车辆")
        params = {
            "params": {
                "ecu_sn": ecu_sn,
                "bike_sn": bike_sn
            }
        }
        try:
            response = RequestUtils().all_request(method="POST", url=url, headers=self.headers, data=json.dumps(params))
            if 'error' in response.json.keys():
                print("bind bike failed")
            else:
                print("bind bike success")
        except Exception as e:
            print("bind bike failed")
            print(e)
        finally:
            return

    def unbind_bike(self, ecu_sn, bike_sn):
        """
        功能：测试环境解绑车辆
        :param ecu_sn: ecu_sn
        :param bike_sn: 车辆编号
        :return: -
        """
        if self.env == "test":
            url = "http://test-inside-ebike-info-api.songguo7.com/ebike/ebike/unbind"
        elif self.env == "online":
            print("online环境不支持解绑车辆")
        params = {
            "params": {
                "ecu_sn": ecu_sn,
                "bike_sn": bike_sn
            }
        }
        try:
            response = RequestUtils().all_request(method="POST", url=url, headers=self.headers,
                                                  data=json.dumps(params))
            if 'error' in response.json.keys():
                print("bind bike failed")
            else:
                print("bind bike success")
        except Exception as e:
            print("bind bike failed")
            print(e)
        finally:
            return

    def query_bike_city(self, bike_sn=None, ecu_sn=None):
        """
        功能：查询bike_sn所属城市
        :param bike_sn: 车辆编号
        :return: -
        """
        sql = ''
        print("bike_sn:{}, ecu_sn:{}".format(bike_sn, ecu_sn))
        if bike_sn:
            sql = '''
                SELECT * FROM ebike_galaxy.bike_bind where bike_sn='{}'
                '''.format(bike_sn)
        elif ecu_sn:
            sql = '''
                SELECT * FROM ebike_galaxy.bike_bind where ecu_sn='{}'
                '''.format(ecu_sn)
        bike_data = DBUtils().conn_db(sql)
        print(bike_data)
        return bike_data

    def change_bike_city(self, bike_sn, city_name):
        """
        功能：更改bike_sn所属城市《用处较小》
        :param bike_sn: 车辆编号
        :param city_name: 城市名称
        :return: -
        """
        city_id = request_data.CITY_DICT_TEST[city_name]
        if city_id == UsefulTools().query_bike_city(bike_sn)[0][12]:
            print("车辆已经在该城市")
            return
        else:
            sql = '''
                    UPDATE ebike_galaxy.bike_bind ebb SET city_id="{}" WHERE ebb.bike_sn='{}';
                '''.format(city_id, bike_sn)
            DBUtils().conn_db(sql)
            print("bike_sn:{} change city to {} success".format(bike_sn, city_name))
            return

    def change_bike_storage_status(self, storage_status, ecu_sn=None, bike_sn=None):
        """
        功能：更改车辆库存状态《用处较小》
        :param ecu_sn: ecu_sn
        :param bike_sn: 车辆编号
        :param city_name: 城市名称
        :param stock_status_text: 库存状态：回收/投放
        :return: -
        """
        sql = ''
        if ecu_sn:
            sql = '''
                UPDATE ebike_galaxy.bike_bind ebb SET storage_status="{}" WHERE ebb.ecu_sn='{}';
            '''.format(STORAGE_STATUS[storage_status], ecu_sn)
        elif bike_sn:
            sql = '''
                UPDATE ebike_galaxy.bike_bind ebb SET storage_status="{}" WHERE ebb.bike_sn='{}';
            '''.format(STORAGE_STATUS[storage_status], bike_sn)
        else:
            print("ecu_sn or bike_sn must be provided")
        print("sql:", sql)
        DBUtils().conn_db(sql)
        print(f"{ecu_sn} {bike_sn}: change bike storage status to {storage_status} success")
        return

    def get_all_city_info(self):
        """
        功能：获取所有城市信息并保存到本地json文件
        :return: 所有城市信息json文件
        """
        url = "https://os-gateway.songguo7.com/api/ebike/management/authorized/city/list"
        params = {}
        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        result = response.json()['data']

        if len(result) == 0:
            print("查询城市信息失败")
            return
        else:
            print("查询城市信息成功")
            print("city_count: ", len(result))
        data_dict = result

        all_city_info = {}
        for data in data_dict:
            all_city_info[data["region_name"]] = data["region_id"]
            if data["sub_region"] is not None:
                print(f"data: {data["sub_region"]}")
                for sub_data in data["sub_region"]:
                    all_city_info[sub_data["region_name"]] = sub_data["region_id"]
                    if sub_data["sub_region"] is not None:
                        print(f"sub_data: {sub_data['sub_region']}")
                        for sub2_data in sub_data["sub_region"]:
                            all_city_info[sub2_data["region_name"]] = sub2_data["region_id"]
                            if sub2_data["sub_region"] is not None:
                                print(f"sub2_data: {sub2_data['sub_region']}")
                                for sub3_data in sub2_data["sub_region"]:
                                    all_city_info[sub3_data["region_name"]] = sub3_data["region_id"]
                                    if sub3_data["sub_region"] is not None:
                                        print(f"sub3_data: {sub3_data['sub_region']}")
                                        all_city_info[sub3_data["region_name"]] = sub3_data["region_id"]
                                    else:
                                        print(f"{sub3_data['region_name']} sub3_data is None")
                                        continue
                                else:
                                    print(f"{sub2_data['region_name']} sub2_data is None")
                                    continue
                        else:
                            print(f"{sub_data['region_name']} sub_data is None")
                            continue
                else:
                    print(f"{data['region_name']} data is None")
                    continue
        else:
            print("data is None")

        print("all_city_info:", all_city_info)
        if os.path.exists(os.path.join(os.getcwd(), "datas/city_info.json")):
            os.remove(os.path.join(os.getcwd(), "datas/city_info.json"))
        with open(os.path.join(os.getcwd(), "datas/city_info.json"), "a", encoding="utf-8") as f:
            f.write(json.dumps(all_city_info, indent=4, ensure_ascii=False))

        if os.path.exists(os.path.join(os.getcwd(), "datas/city_info.yaml")):
            clean_yaml(os.path.join(os.getcwd(), "datas/city_info.yaml"))
            write_yaml(os.path.join(os.getcwd(), "datas/city_info.yaml"), data_dict)

    def get_ota_template_list(self):
        """
        功能：获取测试环境ota模板列表
        :return: -
        """
        url = ""
        if self.env == "test":
            url = "https://test-techgw.songguo7.com/iot-admin/arc/template/page"
        elif self.env == "online":
            url = "https://techgw.songguo7.com/iot-admin/arc/template/page"
        page = 1
        page_size = 100
        params = {
            "params": {
                "page": page,
                "page_size": page_size,
                "package_type": None,
                "product_name": [],
                "template_level": [],
                "before_version": None,
                "after_version": None,
                "create_user": None,
                "template_id": None,
                "factory_use": None
            }
        }

        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        data = response.json()["data"]["item_list"]
        if response.json()["data"]["page_count"] > 1:
            for i in range(2, response.json()["data"]["page_count"] + 1):
                params["params"]["page"] = i
                response = RequestUtils().all_request(url=url, method="post", json=params,
                                                      headers=self.headers)
                data = data + response.json()["data"]["item_list"]
        print("共有 {} 升级模板".format(len(data)))
        file_name = "ota_template_list"
        write_json(file_name, data)
        return data

    def get_ota_package_list(self):
        # 获取ota包信息列表
        url_pkg = ""
        if self.env == "test":
            url_pkg = "https://test-techgw.songguo7.com/iot-admin/arc/package/page"
        elif self.env == "online":
            url_pkg = "https://techgw.songguo7.com/iot-admin/arc/package/page"
        page = 1
        page_size = 10
        params_pkg = {
            "params": {
                "page": page,
                "page_size": page_size,
                "package_type": None,
                "version": None,
                "product_name": None,
                "package_id": None
            }
        }

        response = RequestUtils().all_request(url=url_pkg, method="post", json=params_pkg, headers=self.headers)
        data = response.json()["data"]["item_list"]
        # print(response.json())
        if response.json()["data"]["page_count"] > 1:
            for i in range(2, response.json()["data"]["page_count"] + 1):
                params_pkg["params"]["page"] = i
                response = RequestUtils().all_request(url=url_pkg, method="post", json=params_pkg,
                                                      headers=self.headers)
                data = data + response.json()["data"]["item_list"]
        print("共有 {} 升级包".format(len(data)))
        file_name = "ota_package_list"
        write_json(file_name, data)
        return data

    def create_ota_task(self, ecu_list, product_name, hw_version, package_type, current_version, target_version,
                        mcu_version=None, times=1):
        """
        功能：在iov平台创建OTA升级任务
        :param ecu_sn_list: ecu_sn列表
        :param ota_template_id: ota模板id
        :param description: 任务描述
        """
        template_id = ""
        description = ""
        ota_template_id = ""
        re_ota_template_id = ""

        pkg_type_dict = {
            "控制器包": "CONTROLLER_PACKAGE",
            "固件包": "MCU_PACKAGE"
        }
        hw_version_list = ["2.1.0", "2.1.1", "3.1.0"]
        pkg_type_list = list(pkg_type_dict.keys())
        package_type = pkg_type_dict[package_type]
        for ota_template in self.get_ota_template_list():
            t_product_name = ota_template["product_name"]
            t_hw_version = re.search(r'.*?_(.*?)_', ota_template["template_name"]).group(1)
            t_package_type = ota_template["package_type"]
            t_current_version = re.search(r'.*\"(.*?)\"', ota_template["template_name"]).group(1)
            t_target_version = re.search(r'.*_(.*)', ota_template["template_name"]).group(1)
            t_mcu_version = re.search(r'.*?\"(.*?)\"', ota_template["mcu_upgrade_msg"]).group(1)
            t_status = ota_template["template_state"]

            if package_type == "MCU_PACKAGE":
                if (t_product_name == product_name and t_hw_version == hw_version and
                        t_package_type == package_type and t_current_version == current_version and
                        t_target_version == target_version and t_status == "USEING"):
                    ota_template_id = ota_template["template_id"]
                    print("找到ota upgrade模板：", ota_template_id)
                elif (t_product_name == product_name and t_hw_version == hw_version and
                      t_package_type == package_type and t_current_version == target_version and
                      t_target_version == current_version and t_status == "USEING"):
                    re_ota_template_id = ota_template["template_id"]
                    print("找到re ota upgrade模板：", re_ota_template_id)
            else:
                if mcu_version is None:
                    print("配件升级时，必须指定mcu_version！")
                    return
                else:
                    if (t_product_name == product_name and t_hw_version == hw_version and
                            t_package_type == package_type and t_current_version == current_version and
                            t_target_version == target_version and t_mcu_version == mcu_version and t_status == "USEING"):
                        ota_template_id = ota_template["template_id"]
                        print("找到ota upgrade模板：", ota_template_id)
                    elif (t_product_name == product_name and t_hw_version == hw_version and
                          t_package_type == package_type and t_current_version == target_version and
                          t_target_version == current_version and t_mcu_version == mcu_version and t_status == "USEING"):
                        re_ota_template_id = ota_template["template_id"]
                        print("找到re ota upgrade模板：", re_ota_template_id)

        for i in range(times):
            if i % 2 == 0:
                template_id = ota_template_id
                description = product_name + " " + package_type + " " + current_version + " -> " + target_version
            elif i % 2 == 1:
                template_id = re_ota_template_id
                description = product_name + " " + package_type + " " + target_version + " -> " + current_version
            print(">>> template_id:", template_id, "\n>>> description:", description)
            params = {
                "params": {
                    "task_start_time": int(time.time() * 1000),
                    "task_end_time": int(time.time() * 1000) + (20 * 60 * 1000),
                    "description": description,
                    "ecu_filter": {},
                    "ste_sns": ecu_list,
                    "task_type": "OTA_UPGRADE",
                    "template_id": template_id
                }
            }

            url = ""
            if self.env == "test":
                url = "https://test-techgw.songguo7.com/iot-admin/arc/task/create"
            elif self.env == "online":
                url = "https://techgw.songguo7.com/iot-admin/arc/task/create"
            res = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
            print(f"create info: {res.json()}")
            time.sleep(8 * 60)
            if 'error' in res.text:
                print("create ota task failed, exit")
                os._exit(0)
            else:
                vv = description.split(" ")[-1]
                # print(f"vv: {vv}")
                for ecu in ecu_list:
                #     lastest_info = self.get_logs_query(ecu, cmd=1)
                #     print(f"lastest_info: {lastest_info}")
                #     if f'"MCU版本号: 0x10":"{vv}"' in self.get_logs_query(ecu, cmd=1):
                    db = pymysql.connect(host="localhost", port=3306, user='root', password='00000000', db='testdb')
                    cursor = db.cursor()
                    sql = f"insert into ota_records values (null, {ecu}, 'success', '{description}', default)"
                    cursor.execute(sql)
                    data = cursor.fetchall()
                    db.commit()
                    db.close()
                    cursor.close()
                print(f"create ota task success and upgrade {i+1} times success")
                # DBUtils().conn_db(f"INSERT INTO ota_record (id, ecu, record, description, time) "
                #                   f"VALUES (NULL, '{ecu_list[0]}', 'success', '{description}', NULL)")

    def get_last_gps_info_by_ecu_list(self, ecu_list):
        """
        功能：批量获取设备的最近一包定位信息（需要有车辆绑定关系）《重复的方法和下面get_last_gps_package_info》
        :param ecu_list:ecu列表
        :param env_type:所在环境：online
        :return:
        """
        params = {
            "params": {
                "ste_sns": ecu_list,
                "fields": ["BASE_REPORT_FILED_lastSteGpsTime", "BASE_REPORT_FILED_lastReceiveGpsTime",
                           "GPS_STATUS_FIELD_latitude", "GPS_STATUS_FIELD_longitude", "GPS_STATUS_FIELD_altitude",
                           "GPS_STATUS_FIELD_azimuth", "GPS_STATUS_FIELD_gpsSpeed", "GPS_STATUS_FIELD_totalDistance",
                           "GPS_STATUS_FIELD_singleDistance", "GPS_STATUS_FIELD_hallSpeed"
                           ]
            }
        }

        url = "https://test-inside-iot-report-web.songguo7.com/report/parsed/last/get-batch"
        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        data = response.json()
        if "error" in data.keys():
            self.headers["Cookie"] = DBUtils().update_token(self.env)
            response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
            data = response.json()
        print(data["data"])
        return data["data"]

    def get_last_helmet_info(self, ecu_list):
        """
        功能：批量获取设备的最近的头盔信息（需要有车辆绑定关系）
        :param ecu_list:ecu列表
        :param env_type:所在环境：online
        :return: 打印返回最近一包包含头盔的信息
        """
        params = {
            "params": {
                "ste_sns": ecu_list,
                "scopes": [
                    "STE_INFO",
                    "BIKE_STATUS"
                ]
            }
        }

        url = "https://test-inside-iot-report-web.songguo7.com/report/parsed/scopes/last/batch-get"
        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        data = response.json()
        if "error" in data.keys():
            self.headers["Cookie"] = DBUtils().update_token(self.env)
            response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
            data = response.json()
        print(data["data"])
        return data["data"]

    def get_last_gps_package_info(self, ecu_list):
        """
        功能：批量获取设备的最近一包定位信息（需要有车辆绑定关系）
        :param ecu_list:ecu列表
        :param env_type:所在环境：online
        :return: 打印最近一包定位信息
        """
        params = {
            "params": {
                "ste_sn": "",
                "bike_sn": "",
                "scopes": [
                    "STE_INFO",
                    "BIKE_STATUS",
                    "CAL_BATTERY_INFO",
                    "BLE_INFO",
                    "CONF_INFO",
                    "BASE_REPORT",
                    "BATTERY_STATUS",
                    "GPS_STATUS",
                    "BIKE_STATUS",
                    "STE_INFO"
                ]
            }
        }

        select_url = "https://test-inside-iot-report-web.songguo7.com/report/parsed/last/get"
        for ecu_sn in ecu_list:
            params["params"]["ste_sn"] = ecu_sn
            response = RequestUtils().all_request(method="post", url=select_url, json=params, headers=self.headers, timeout=None)
            data = response.json()
            print(data)

    def get_bike_info2execl(self, region_name, product_name, storage_status, firmware_versions=None):
        """
        功能：获取线上环境车辆列表到本地xlsx文件
        :param region_name: 城市名
        :param product_name: 产品名
        :param storage_status: 存储状态
        :param firmware_versions: 固件版本列表
        :return: 车辆列表xlsx文件 /commons
        """
        # data_title = []  # 可自定义数据表头,默认全量
        data_title = [
            'bike_sn',
            'ecu_sn',
            'bike_model',
            'product_name',
            'change_battery_status',
            'move_status',
            'firmware_version',
            'factory_name',
            'hardware_version',
            'voice_version',
            'city_name',
            'storage_status',
            'controller_version',
            'bms_version',
            'helmet_lock_version',
            'tbc_version',
            'weight_sensor_version',
            'display_version',
            'communication_extension_version',
            'parking_camera_version',
            'helmet_lock_ble_version'
        ]

        battery_soc_start = 0
        battery_soc_end = 100
        page_size = 100  # 每页数据量, 最大100
        region_id = json.loads(open(os.path.join(os.getcwd(), "commons/city_info.json"),
                                    "r", encoding="utf-8").read())[region_name]

        if not data_title:  # 如果没有自定义数据表头，则使用默认数据表头
            data_title = [
                'bikeSn',  # 车辆编号
                'ecuSn',  # ECU编号
                'bikeModel',  # 车辆型号
                'bikeQrCode',
                'cityName',  # 城市名
                'storageStatus',  # 存储状态
                'firstOperationTime',
                'productName',  # 产品名
                'ecuFactory',
                'online',  # 在线状态
                'mobileNetwork',
                'imsi',
                'totalDistance',
                'latitude',
                'longitude',
                'lastReportTime',
                'lastSteLoginTime',
                'lastSteHeartbeatTime',
                'lastSteGpsTime',
                'usageStatus',
                'hubMotorLockStatus',
                'accStatus',
                'batteryVacancyStatus',
                'motionStatus',
                'sleepStatus',
                'ridingStatus',
                'bluetoothStatus',
                'rearHubLockStatus',
                'twistGripStatus',
                'batteryLockStatus',
                'batterySnStatus',
                'batteryVoltage',
                'hardwareVersion',  # 硬件版本
                'bmsVersion',  # BMS版本
                'parkingCameraVersion',  # 相机版本
                'protocolVersion',
                'rearHubLockVersion',
                'tbcVersion',
                'firmwareVersion',  # 固件版本
                'temperature',
                'batterySn',
                'batterySurplusCapacity',
                'batteryUseTime',
                'communicationModuleVersion',
                'helmetLockVersion',
                'batterySoh',
                'cycleCount',
                'absoluteFullCapacity',
                'absoluteSoc',
                'batterySoc',
                'communicationExtensionVersion',
                'helmetLockBleVersion',
                'weightSensorVersion',
                'voiceVersion',
                'displayVersion',
                'controllerVersion'
            ]

        params = {
            'params': {
                'sn': '',
                'ecu_sn': '',
                'bike_model': '',
                'region_id': region_id,
                'storage_status': request_data.STORAGE_STATUS[storage_status],
                'investTime': '',
                'orderTime': '',
                'movingTime': '',
                'powerTime': '',
                'maintenanceTime': '',
                'serviceTime': '',
                'defaultExpandedKey': [],
                'product_name': product_name.upper(),
                'firmware_versions': firmware_versions,
                'online': True,
                'battery_soc_start': battery_soc_start,
                'battery_soc_end': battery_soc_end,
                'bike_sns_str': '',
                'bike_sns': [],
                'ecu_sns_str': '',
                'ecu_sns': [],
                'bike_qr_codes_str': '',
                'bike_qr_codes': [],
                'hardware_versions': [],
                'controller_versions': [],
                'rear_hub_lock_versions': [],
                'helmet_lock_versions': [],
                'tbc_versions': [],
                'weight_sensor_versions': [],
                'display_versions': [],
                'communication_extension_versions': [],
                'bms_versions': [],
                'parking_camera_versions': [],
                'helmet_lock_ble_versions': [],
                'options': '',
                'lastSteHeartbeatTime': '',
                'page': 1,
                'page_size': page_size,
                'first_operation_start_time': '',
                'first_operation_end_time': '',
                'last_order_create_start_time': '',
                'last_order_create_end_time': '',
                'last_move_start_time': '',
                'last_move_end_time': '',
                'last_maintain_start_time': '',
                'last_maintain_end_time': '',
                'last_change_battery_start_time': '',
                'last_change_battery_end_time': '',
                'last_repair_start_time': '',
                'last_repair_end_time': '',
                'last_ste_heartbeat_start_time': '',
                'last_ste_heartbeat_end_time': ''
            },
            'column_names': data_title
        }
        url = ""
        if self.env == "test":
            url = "http://test-os-gateway.songguo7.com/api/ebike/management/info/list"
        elif self.env == "online":
            url = "https://os-gateway.songguo7.com/api/ebike/management/info/list"
        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        data = response.json()["data"]["item_list"]
        # print(response.json())
        if response.json()["data"]["page_count"] > 1:
            for i in range(2, response.json()["data"]["page_count"] + 1):
                params["params"]["page"] = i
                response = RequestUtils().all_request(url=url, method="post", json=params,
                                                      headers=self.headers)
                data = data + response.json()["data"]["item_list"]
        print("查询成功，共有{}辆车数据".format(len(data)))

        with open(os.path.join(os.getcwd(), "commons/online_env_bike_info_list.json"), "w", encoding="utf-8") as f:
            f.write(json.dumps(data, indent=4, ensure_ascii=False))

        if "error" in response.json().keys():
            print("查询失败，请检查网络或参数是否正确")
        else:
            write_excel(data_title, data)
            print("车辆列表xlsx文件已保存到{}目录下".format(os.path.join(os.getcwd(), "commons")))

    def get_ota_task_list(self):
        """
        获取OTA任务列表
        :param task_state: 任务状态，枚举值：EXECUTING、END、ERROR_END、CLOSE
        :param create_user: 创建人
        :return:
        """
        task_state = "END"
        create_user = ""

        url = "https://inside-techgw.songguo7.com/iot-admin/arc/task/page"
        params = {
            "params": {
                "page": None,
                "page_size": 1000,
                "task_id": None,
                "task_state": task_state,
                "task_type_enum": "OTA_UPGRADE"
            }
        }
        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        # ota_task_id_list = [items['id'] for items in response.json()['data']['item_list']]
        if create_user:
            ota_task_id_list = [items['id'] for items in response.json()['data']['item_list']
                                if items['create_user'] == create_user]
        else:
            ota_task_id_list = [items['id'] for items in response.json()['data']['item_list']]

        print(f"COUNT: {len(ota_task_id_list)} \nota_task_id_list: \n{ota_task_id_list}")
        print("HEADERS: ", response.headers)
        return ota_task_id_list

    def ota_task_operate(self):
        """
        操作OTA任务
        :param operate: 操作类型，枚举值：CLOSE
        :return:
        """
        operate = "CLOSE"

        url = "https://inside-techgw.songguo7.com/iot-admin/arc/task/state/operate"
        ota_task_id_list = UsefulTools().get_ota_task_list()
        for task_id in ota_task_id_list:
            params = {
                "params": {
                    "task_id": task_id,
                    "task_state": operate
                }
            }
            response = RequestUtils().all_request(url=url, method="post", json=params,
                                                  headers=self.headers)
            if response.json()['code'] != 0:
                print(response.json())
                break
            else:
                print(f"{task_id} {operate} 操作成功")

    def send_command_to_ecu(self, ecu_list, command, param=None):
        """
        功能：通过iov平台-进行指令下发
        :param channel_type: 通道类型：NET、SMS、BLUETOOTH
        :param env_type: 设备所在的环境，枚举值：test、online
        :param ecu: ECU编号
        :param command_type:指令类型
        :param params_dict:参数
        :return:
        """
        url = ""
        if self.env == "test":
            url = "https://test-os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/send"
        elif self.env == "online":
            url = "https://os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/send"
        # create params
        if command is None:
            print("请输入指令")
            return
        elif command == "参数查询" or command == "参数设置":
            if param is None:
                print("请输入参数")
                return

        command_type = [x["command_code"] for x in COMMAND_DICT_LIST if
                        x["command_note"] == command][0]  # COMMAND_DICT_LIST[]
        params = {
            "params": {
                "steStr": "\n".join(ecu_list),
                "channel_type": "NET",
                "command_type": command_type,
                "need_ack": True,
                "ste_sns": [str(ecu) for ecu in ecu_list],
                "tenant_code": "1",
                "param": None
            }
        }

        if param:
            params["params"]["param"] = param

        # print(">>>> send_command params: ", params)
        # print(self.headers)
        response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
        content = response.json()
        if "error" in content.keys():
            self.headers["Cookie"] = DBUtils().update_token(self.env)
            response = RequestUtils().all_request(url=url, method="post", json=params, headers=self.headers)
            content = response.json()
        # print(">>>> send_command result: ", content)

        # all command result
        sleeptime = 30
        interval = 0.3
        for i in range(0, int(sleeptime / interval) + 1):
            print("\r正在加载:" + "|" + "*" * i + " " * (int(sleeptime / interval) + 1 - i) + "|" + str(i) + "%", end="")
            time.sleep(interval)
        print("\n")
        result_url = ""
        if self.env == "test":
            result_url = "http://test-os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/result"
        elif self.env == "online":
            result_url = "https://os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/result"
        result_params = {
            "params": {
                "command_nos": [
                    item["command_no"] for item in
                    content["data"]["send_success_commands"]
                ],
            }
        }
        print(">>>> result_params:", result_params)
        response_result = RequestUtils().all_request(url=result_url, method="post", json=result_params,
                                                     headers=self.headers)
        content_result = response_result.json()
        # print(">>>> send_command_result:", content_result)
        for item in content_result["data"]:
            if item["command_result"] == 200:
                print(f"{item['ste_sn']} 指令下发成功")
            else:
                print(f"{item['ste_sn']} 指令下发失败, 返回码: {item['command_result']}")
        command_no_list = [item["command_no"] for item in content["data"]["send_success_commands"]]
        return command_no_list

    def get_logs_query(self, ecu, time_linetypes=None, cmd=None, number=None, start_time=None, end_time=None):
        """
        获取日志查询
        :param time_linetypes: 日志类型，枚举值：CMD、GPS、BMS、BATTERY、WIFI、BLE、ALARM、STATUS、EVENT、OTHER
        :param cmd: 指令
        :param number: 日志条数
        :param start_time: 开始时间
        :param ecu: ECU编号
        :return:
        """
        if start_time is None:
            start_time = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.localtime(time.time() - 4 * 60 * 60))
            end_time = time.strftime("%Y-%m-%dT%H:%M:%S.998Z", time.localtime(time.time()))
        else:
            start_time = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.strptime(start_time, "%Y-%m-%d %H:%M:%S"))
            end_time = time.strftime("%Y-%m-%dT%H:%M:%S.998Z", time.strptime(end_time, "%Y-%m-%d %H:%M:%S"))
        if cmd is None:
            cmd = ""
        query = {
            "params": {
                "page_size": "1000",
                "bike_sn": "",
                "ecu_sn": ecu,
                "cmd": cmd,
                "cmd_code": "",
                "timeline_start_time": start_time,
                "timeline_end_time": end_time,
                "time_linetypes": [time_linetypes] if time_linetypes is not None else [],
                "scroll_id": "",
                "gsm_signal_strength": "",
                "standby_battery_capacity": "",
                "parse_able": True
            }
        }
        print("传入参数")
        print(query)
        datas = json.dumps(query)
        url = "http://test-os-gateway.songguo7.com/api/iot-timeline/timeline/list"
        headers = DBUtils().get_headers("test")
        response = requests.post(url=url, data=datas, headers=headers, timeout=None)
        # response = RequestUtils().all_request(method="post", url=url, data=datas, headers=headers, timeout=None)
        data = response.json()
        if "error" in data.keys():
            headers = DBUtils().update_headers("test")
            response = RequestUtils().all_request(method="post", url=url, data=datas, headers=headers, timeout=None)
            # response = requests.post(url=url, data=datas, headers=headers, timeout=None)
            data = response.json()["data"]
            time_line_record_list = data["time_line_record_entities"]
            print(time_line_record_list)
            if number is None:
                return time_line_record_list[0]
            else:
                return time_line_record_list
        else:
            data = data["data"]
            time_line_record_list = data["time_line_record_entities"]
            print("结果")
            print(time_line_record_list)
            try:
                '''
                {'bike_sn': None, 'time_linetype': 20, 'bike_model': None, 'city_id': None, 'ecu_sn': '8222420010020050', 'ecu_type': None, 'ecu_factory': None, 'firmware_version': None, 'product_name': None, 'login_reason': None, 'battery_sn': None, 'battery_soc': None, 'battery_surplus_capacity': None, 'absolute_soc': None, 'absolute_full_capacity': None, 'battery_soh': None, 'electric_current': None, 'battery_voltage': None, 'cycle_count': None, 'usage_status': None, 'motion_status': None, 'hub_motor_lock_status': None, 'acc_status': None, 'sleep_status': None, 'bluetooth_status': None, 'battery_lock_status': None, 'riding_status': None, 'battery_vacancy_status': None, 'twist_grip_status': None, 'rear_hub_lock_status': None, 'alarm_type': None, 'alarm_status': None, 'cmd': None, 'channel_type': None, 'need_ack': None, 'cmd_no': None, 'cmd_type': 1, 'status': 200, 'error_code': None, 'msg_id': '08816e39671243029e21d0f7651158db', 'msg_type': None, 'rtk_type': None, 'params': None, 'sim': None, 'cmd_code': 344, 'time': '2025-01-02 18:00:20.641', 'cmd_to_ecu_status': None, 'cmd_to_ecu_time': None, 'ext': '{"esn":"8222420010020050","data":{"code":"344","payload":{"result":0,"reserved":"AA==","dataType":0,"msgId":"08816e39671243029e21d0f7651158db","sen":11,"ts":1735812020},"type":1,"msg_id":"08816e39671243029e21d0f7651158db","status":"200","ts":1735812020000},"action":7,"bike_sn":"8222420010020050","ts":1735812020641}', 'offline_type': None, 'offline_info': None, 'start_time': None, 'end_time': None, 'offline_time': None, 'gsm_signal_strength': None, 'standby_battery_capacity': None}
                '''
                items = dict()
                print(len(time_line_record_list))
                with open(os.path.join(os.getcwd(), f"datas/time_line_record_{ecu}_{start_time}_{end_time}_{cmd}.json"),
                          "w") as f:
                    f.write(json.dumps(time_line_record_list, indent=4, ensure_ascii=False))
            except:
                items = dict()

            """
            if number is None:
                try:
                    return time_line_record_list[0]
                except:
                    print("here has a error!")
            else:
                return time_line_record_list
            """
        # info to excel
        wookbook = xlwt.Workbook(encoding='utf-8')
        wooksheet = wookbook.add_sheet('Sheet1')
        i = 0
        for item in time_line_record_list:
            wooksheet.write(i, 0, item['time'])
            wooksheet.write(i, 1, json.loads(item['ext'])['data']['status'])
            wooksheet.write(i, 2, json.loads(item['ext'])['data']['code'])
            i += 1
        wookbook.save(os.path.join(os.getcwd(), f"datas/time_line_record_{ecu}_{start_time}_{end_time}_{cmd}.xls"))




if __name__ == "__main__":
    ecu_list = ['8212405010000014']
    # UsefulTools().get_last_gps_package_info(ecu_list)
    UsefulTools().create_ota_task("8212405010000014", "DLS", "3.1.0",
                                  "控制器包", "7.0.67", "7.0.66",
                                  "1.0.23", 2)
    # UsefulTools().get_logs_query(10)
    # UsefulTools().send_command_to_ecu(ecu_list, "开锁")
    pass
